package glog

import (
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/cloudwego/hertz/pkg/common/hlog"
)

// LogLevel 日志级别
type LogLevel int

const (
	LevelTrace LogLevel = iota
	LevelDebug
	LevelInfo
	LevelNotice
	LevelWarn
	LevelError
	LevelFatal
)

// Config 日志配置
type Config struct {
	// 日志文件路径
	FilePath string
	// 日志级别
	Level LogLevel
	// 是否同时输出到控制台
	Console bool
	// 文件最大大小(MB)
	MaxSize int
	// 最大保留天数
	MaxAge int
	// 日志格式化函数
	Formatter func(level LogLevel, msg string, kvs ...interface{}) string
}

// Logger 自定义日志器
type Logger struct {
	config *Config
	file   *os.File
	writer io.Writer
	mutex  sync.RWMutex
}

// 默认格式化函数
func defaultFormatter(level LogLevel, msg string, kvs ...interface{}) string {
	levelStr := []string{"TRACE", "DEBUG", "INFO", "NOTICE", "WARN", "ERROR", "FATAL"}[level]
	timestamp := time.Now().Format("2006-01-02 15:04:05.000")

	result := fmt.Sprintf("[%s] [%s] %s", timestamp, levelStr, msg)

	// 处理键值对参数
	if len(kvs) > 0 {
		result += " |"
		for i := 0; i < len(kvs); i += 2 {
			if i+1 < len(kvs) {
				result += fmt.Sprintf(" %v=%v", kvs[i], kvs[i+1])
			} else {
				result += fmt.Sprintf(" %v", kvs[i])
			}
		}
	}

	return result + "\n"
}

// NewLogger 创建新的日志器实例
func NewLogger(config *Config) (*Logger, error) {
	if config == nil {
		return nil, fmt.Errorf("config cannot be nil")
	}

	// 设置默认值
	if config.Formatter == nil {
		config.Formatter = defaultFormatter
	}
	if config.MaxSize <= 0 {
		config.MaxSize = 100 // 默认100MB
	}
	if config.MaxAge <= 0 {
		config.MaxAge = 7 // 默认保留7天
	}

	logger := &Logger{
		config: config,
	}

	// 初始化文件输出
	if err := logger.initFile(); err != nil {
		return nil, err
	}

	return logger, nil
}

// initFile 初始化日志文件
func (l *Logger) initFile() error {
	if l.config.FilePath == "" {
		// 如果没有指定文件路径，只输出到控制台
		if l.config.Console {
			l.writer = os.Stdout
		} else {
			l.writer = io.Discard
		}
		return nil
	}

	// 创建目录
	dir := filepath.Dir(l.config.FilePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed to create log directory: %v", err)
	}

	// 打开文件
	file, err := os.OpenFile(l.config.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return fmt.Errorf("failed to open log file: %v", err)
	}

	l.file = file

	// 设置输出writer
	if l.config.Console {
		l.writer = io.MultiWriter(file, os.Stdout)
	} else {
		l.writer = file
	}

	return nil
}

// Close 关闭日志器
func (l *Logger) Close() error {
	l.mutex.Lock()
	defer l.mutex.Unlock()

	if l.file != nil {
		return l.file.Close()
	}
	return nil
}

// shouldLog 检查是否应该记录该级别的日志
func (l *Logger) shouldLog(level LogLevel) bool {
	return level >= l.config.Level
}

// writeLog 写入日志
func (l *Logger) writeLog(level LogLevel, msg string, kvs ...interface{}) {
	if !l.shouldLog(level) {
		return
	}

	l.mutex.RLock()
	defer l.mutex.RUnlock()

	if l.writer == nil {
		return
	}

	formatted := l.config.Formatter(level, msg, kvs...)
	l.writer.Write([]byte(formatted))
}

// 实现 hlog.FullLogger 接口的所有方法
// 这些方法可以让Logger兼容hertz的hlog接口

// Trace 记录trace级别日志
func (l *Logger) Trace(v ...interface{}) {
	l.writeLog(LevelTrace, fmt.Sprint(v...))
}

// Debug 记录debug级别日志
func (l *Logger) Debug(v ...interface{}) {
	l.writeLog(LevelDebug, fmt.Sprint(v...))
}

// Info 记录info级别日志
func (l *Logger) Info(v ...interface{}) {
	l.writeLog(LevelInfo, fmt.Sprint(v...))
}

// Notice 记录notice级别日志
func (l *Logger) Notice(v ...interface{}) {
	l.writeLog(LevelNotice, fmt.Sprint(v...))
}

// Warn 记录warn级别日志
func (l *Logger) Warn(v ...interface{}) {
	l.writeLog(LevelWarn, fmt.Sprint(v...))
}

// Error 记录error级别日志
func (l *Logger) Error(v ...interface{}) {
	l.writeLog(LevelError, fmt.Sprint(v...))
}

// Fatal 记录fatal级别日志
func (l *Logger) Fatal(v ...interface{}) {
	l.writeLog(LevelFatal, fmt.Sprint(v...))
	os.Exit(1)
}

// Tracef 记录trace级别格式化日志
func (l *Logger) Tracef(format string, v ...interface{}) {
	l.writeLog(LevelTrace, fmt.Sprintf(format, v...))
}

// Debugf 记录debug级别格式化日志
func (l *Logger) Debugf(format string, v ...interface{}) {
	l.writeLog(LevelDebug, fmt.Sprintf(format, v...))
}

// Infof 记录info级别格式化日志
func (l *Logger) Infof(format string, v ...interface{}) {
	l.writeLog(LevelInfo, fmt.Sprintf(format, v...))
}

// Noticef 记录notice级别格式化日志
func (l *Logger) Noticef(format string, v ...interface{}) {
	l.writeLog(LevelNotice, fmt.Sprintf(format, v...))
}

// Warnf 记录warn级别格式化日志
func (l *Logger) Warnf(format string, v ...interface{}) {
	l.writeLog(LevelWarn, fmt.Sprintf(format, v...))
}

// Errorf 记录error级别格式化日志
func (l *Logger) Errorf(format string, v ...interface{}) {
	l.writeLog(LevelError, fmt.Sprintf(format, v...))
}

// Fatalf 记录fatal级别格式化日志
func (l *Logger) Fatalf(format string, v ...interface{}) {
	l.writeLog(LevelFatal, fmt.Sprintf(format, v...))
	os.Exit(1)
}

// CtxTracef 带上下文的trace级别格式化日志
func (l *Logger) CtxTracef(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelTrace, fmt.Sprintf(format, v...))
}

// CtxDebugf 带上下文的debug级别格式化日志
func (l *Logger) CtxDebugf(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelDebug, fmt.Sprintf(format, v...))
}

// CtxInfof 带上下文的info级别格式化日志
func (l *Logger) CtxInfof(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelInfo, fmt.Sprintf(format, v...))
}

// CtxNoticef 带上下文的notice级别格式化日志
func (l *Logger) CtxNoticef(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelNotice, fmt.Sprintf(format, v...))
}

// CtxWarnf 带上下文的warn级别格式化日志
func (l *Logger) CtxWarnf(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelWarn, fmt.Sprintf(format, v...))
}

// CtxErrorf 带上下文的error级别格式化日志
func (l *Logger) CtxErrorf(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelError, fmt.Sprintf(format, v...))
}

// CtxFatalf 带上下文的fatal级别格式化日志
func (l *Logger) CtxFatalf(ctx context.Context, format string, v ...interface{}) {
	l.writeLog(LevelFatal, fmt.Sprintf(format, v...))
	os.Exit(1)
}

// SetLevel 设置日志级别
func (l *Logger) SetLevel(level hlog.Level) {
	l.mutex.Lock()
	defer l.mutex.Unlock()

	// 转换hertz的日志级别到我们的日志级别
	switch level {
	case hlog.LevelTrace:
		l.config.Level = LevelTrace
	case hlog.LevelDebug:
		l.config.Level = LevelDebug
	case hlog.LevelInfo:
		l.config.Level = LevelInfo
	case hlog.LevelNotice:
		l.config.Level = LevelNotice
	case hlog.LevelWarn:
		l.config.Level = LevelWarn
	case hlog.LevelError:
		l.config.Level = LevelError
	case hlog.LevelFatal:
		l.config.Level = LevelFatal
	}
}

// SetOutput 设置输出目标
func (l *Logger) SetOutput(writer io.Writer) {
	l.mutex.Lock()
	defer l.mutex.Unlock()
	l.writer = writer
}

// 全局日志实例管理
var (
	defaultLogger *Logger
	loggerMutex   sync.RWMutex
)

// Init 初始化默认日志器
func Init(config *Config) error {
	logger, err := NewLogger(config)
	if err != nil {
		return err
	}

	loggerMutex.Lock()
	defer loggerMutex.Unlock()

	// 如果已有默认日志器，先关闭它
	if defaultLogger != nil {
		defaultLogger.Close()
	}

	defaultLogger = logger
	return nil
}

// GetLogger 获取默认日志器实例
func GetLogger() *Logger {
	loggerMutex.RLock()
	defer loggerMutex.RUnlock()

	if defaultLogger == nil {
		// 如果没有初始化，创建一个默认的控制台输出日志器
		config := &Config{
			Level:   LevelInfo,
			Console: true,
		}
		defaultLogger, _ = NewLogger(config)
	}

	return defaultLogger
}

// 便捷的全局日志方法
// 这些方法使用默认的日志器实例

// Trace 全局trace日志
func Trace(v ...interface{}) {
	GetLogger().Trace(v...)
}

// Debug 全局debug日志
func Debug(v ...interface{}) {
	GetLogger().Debug(v...)
}

// Info 全局info日志
func Info(v ...interface{}) {
	GetLogger().Info(v...)
}

// Notice 全局notice日志
func Notice(v ...interface{}) {
	GetLogger().Notice(v...)
}

// Warn 全局warn日志
func Warn(v ...interface{}) {
	GetLogger().Warn(v...)
}

// Error 全局error日志
func Error(v ...interface{}) {
	GetLogger().Error(v...)
}

// Fatal 全局fatal日志
func Fatal(v ...interface{}) {
	GetLogger().Fatal(v...)
}

// Tracef 全局trace格式化日志
func Tracef(format string, v ...interface{}) {
	GetLogger().Tracef(format, v...)
}

// Debugf 全局debug格式化日志
func Debugf(format string, v ...interface{}) {
	GetLogger().Debugf(format, v...)
}

// Infof 全局info格式化日志
func Infof(format string, v ...interface{}) {
	GetLogger().Infof(format, v...)
}

// Noticef 全局notice格式化日志
func Noticef(format string, v ...interface{}) {
	GetLogger().Noticef(format, v...)
}

// Warnf 全局warn格式化日志
func Warnf(format string, v ...interface{}) {
	GetLogger().Warnf(format, v...)
}

// Errorf 全局error格式化日志
func Errorf(format string, v ...interface{}) {
	GetLogger().Errorf(format, v...)
}

// Fatalf 全局fatal格式化日志
func Fatalf(format string, v ...interface{}) {
	GetLogger().Fatalf(format, v...)
}

// WithFields 创建带字段的日志条目
func WithFields(kvs ...interface{}) *LogEntry {
	return &LogEntry{
		logger: GetLogger(),
		fields: kvs,
	}
}

// LogEntry 日志条目，支持结构化日志
type LogEntry struct {
	logger *Logger
	fields []interface{}
}

// Trace 条目trace日志
func (e *LogEntry) Trace(msg string) {
	e.logger.writeLog(LevelTrace, msg, e.fields...)
}

// Debug 条目debug日志
func (e *LogEntry) Debug(msg string) {
	e.logger.writeLog(LevelDebug, msg, e.fields...)
}

// Info 条目info日志
func (e *LogEntry) Info(msg string) {
	e.logger.writeLog(LevelInfo, msg, e.fields...)
}

// Notice 条目notice日志
func (e *LogEntry) Notice(msg string) {
	e.logger.writeLog(LevelNotice, msg, e.fields...)
}

// Warn 条目warn日志
func (e *LogEntry) Warn(msg string) {
	e.logger.writeLog(LevelWarn, msg, e.fields...)
}

// Error 条目error日志
func (e *LogEntry) Error(msg string) {
	e.logger.writeLog(LevelError, msg, e.fields...)
}

// Fatal 条目fatal日志
func (e *LogEntry) Fatal(msg string) {
	e.logger.writeLog(LevelFatal, msg, e.fields...)
	os.Exit(1)
}

// Tracef 条目trace格式化日志
func (e *LogEntry) Tracef(format string, v ...interface{}) {
	e.logger.writeLog(LevelTrace, fmt.Sprintf(format, v...), e.fields...)
}

// Debugf 条目debug格式化日志
func (e *LogEntry) Debugf(format string, v ...interface{}) {
	e.logger.writeLog(LevelDebug, fmt.Sprintf(format, v...), e.fields...)
}

// Infof 条目info格式化日志
func (e *LogEntry) Infof(format string, v ...interface{}) {
	e.logger.writeLog(LevelInfo, fmt.Sprintf(format, v...), e.fields...)
}

// Noticef 条目notice格式化日志
func (e *LogEntry) Noticef(format string, v ...interface{}) {
	e.logger.writeLog(LevelNotice, fmt.Sprintf(format, v...), e.fields...)
}

// Warnf 条目warn格式化日志
func (e *LogEntry) Warnf(format string, v ...interface{}) {
	e.logger.writeLog(LevelWarn, fmt.Sprintf(format, v...), e.fields...)
}

// Errorf 条目error格式化日志
func (e *LogEntry) Errorf(format string, v ...interface{}) {
	e.logger.writeLog(LevelError, fmt.Sprintf(format, v...), e.fields...)
}

// Fatalf 条目fatal格式化日志
func (e *LogEntry) Fatalf(format string, v ...interface{}) {
	e.logger.writeLog(LevelFatal, fmt.Sprintf(format, v...), e.fields...)
	os.Exit(1)
}

// DefaultConfig 返回默认配置
func DefaultConfig(filePath string) *Config {
	return &Config{
		FilePath:  filePath,
		Level:     LevelInfo,
		Console:   false,
		MaxSize:   100,
		MaxAge:    7,
		Formatter: defaultFormatter,
	}
}

// Close 关闭默认日志器
func Close() error {
	loggerMutex.Lock()
	defer loggerMutex.Unlock()

	if defaultLogger != nil {
		err := defaultLogger.Close()
		defaultLogger = nil
		return err
	}
	return nil
}
